package com.own.component.store.core.util.base;

import com.own.component.common.util.encrypt.EncryptUtil;
import com.own.component.common.util.encrypt.model.CustomEncryptKey;
import com.own.component.store.core.Store;
import com.own.component.store.core.constant.ConstantCommon;
import com.own.component.store.core.em.StoreExceptionEnum;
import com.own.component.store.core.exception.StoreException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.Duration;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Collectors;

/**
 * RsaKeyUtil
 *
 * @author chenxueli
 * @date 2022-08-16 16:33:00
 */
@Slf4j
@Component
public class RsaKeyUtil {

    @Resource
    private Store<String> store;

    /**
     * 获取秘钥信息
     *
     * @param sign 标识信息
     * @return 秘钥信息
     */
    public CustomEncryptKey build(String sign) {
        if (StringUtils.isBlank(sign)) {
            throw new StoreException(StoreExceptionEnum.SIGN_IS_NULL);
        }
        if (sign.length() > 64) {
            throw new StoreException(StoreExceptionEnum.SIGN_IS_TOO_LONG);
        }
        var key = EncryptUtil.RSA.buildKey();
        store.value().set(ConstantCommon.RSA_PRIVATE_KEY + sign, key.getPrivateKey(), Duration.ofMinutes(10L));
        store.value().set(ConstantCommon.RSA_PUBLIC_KEY + sign, key.getPublicKey(), Duration.ofMinutes(10L));
        return key;
    }

    /**
     * 根据公钥加密数据
     *
     * @param sign    标识信息
     * @param content 待加密的内容
     * @return 加密数据
     */
    public String encrypt(String sign, String content) {
        var publicKey = store.value().get(ConstantCommon.RSA_PUBLIC_KEY + sign);
        // 公钥为一次性的数据，直接删除
        if (StringUtils.isBlank(publicKey)) {
            throw new StoreException(StoreExceptionEnum.PUBLIC_KEY_IS_NULL);
        }
        store.value().remove(ConstantCommon.RSA_PUBLIC_KEY + sign);
        // 加密数据
        return EncryptUtil.RSA.encrypt(content, CustomEncryptKey.builder().publicKey(publicKey).build());
    }


    /**
     * 根据公钥加密数据
     *
     * @param sign  标识信息
     * @param array 待加密的内容
     * @return 加密数据
     */
    public List<String> encrypt(String sign, String... array) {
        var publicKey = store.value().get(ConstantCommon.RSA_PUBLIC_KEY + sign);
        // 公钥为一次性的数据，直接删除
        if (StringUtils.isBlank(publicKey)) {
            throw new StoreException(StoreExceptionEnum.PUBLIC_KEY_IS_NULL);
        }
        store.value().remove(ConstantCommon.RSA_PUBLIC_KEY + sign);
        // 加密数据
        var key = CustomEncryptKey.builder().publicKey(publicKey).build();
        return Arrays.stream(array).map(content -> EncryptUtil.RSA.encrypt(content, key)).collect(Collectors.toList());
    }

    /**
     * 根据私钥加密数据
     *
     * @param sign    标识信息
     * @param content 待解密的内容
     * @return 明文数据
     */
    public String decrypt(String sign, String content) {
        return decrypt(sign, content, true);
    }

    /**
     * 根据私钥加密数据
     *
     * @param sign     标识信息
     * @param content  待解密的内容
     * @param consumer 设置解密后的值
     * @return 明文数据
     */
    public String decrypt(String sign, String content, Consumer<String> consumer) {
        if (StringUtils.isNotBlank(sign)) {
            var password = decrypt(sign, sign);
            consumer.accept(password);
        }
        return content;
    }


    /**
     * 根据私钥加密数据
     *
     * @param sign  标识信息
     * @param array 待解密的内容
     * @return 明文数据
     */
    public List<String> decrypt(String sign, String... array) {
        if (StringUtils.isBlank(sign)) {
            return Arrays.stream(array).collect(Collectors.toList());
        }
        var privateKey = store.value().get(ConstantCommon.RSA_PRIVATE_KEY + sign);
        // 私钥钥为一次性的数据，直接删除
        if (StringUtils.isBlank(privateKey)) {
            throw new StoreException(StoreExceptionEnum.PUBLIC_KEY_IS_NULL);
        }
        // 删除私钥和公钥信息
        store.value().remove(ConstantCommon.RSA_PRIVATE_KEY + sign);
        store.value().remove(ConstantCommon.RSA_PUBLIC_KEY + sign);
        // 解密数据
        var key = CustomEncryptKey.builder().privateKey(privateKey).build();
        return Arrays.stream(array).map(content -> EncryptUtil.RSA.decrypt(content, key)).collect(Collectors.toList());
    }

    /**
     * 根据私钥加密数据
     *
     * @param sign       标识信息
     * @param content    待解密的内容
     * @param deleteFlag 删除标识
     * @return 明文数据
     */
    public String decrypt(String sign, String content, boolean deleteFlag) {
        if (StringUtils.isBlank(sign)) {
            return content;
        }
        var privateKey = store.value().get(ConstantCommon.RSA_PRIVATE_KEY + sign);
        // 私钥钥为一次性的数据，直接删除
        if (StringUtils.isBlank(privateKey)) {
            throw new StoreException(StoreExceptionEnum.PUBLIC_KEY_IS_NULL);
        }
        // 删除私钥和公钥信息
        if (deleteFlag) {
            deleteSign(sign);
        }
        // 解密数据
        return EncryptUtil.RSA.decrypt(content, CustomEncryptKey.builder().privateKey(privateKey).build());
    }

    /**
     * 删除加密的key
     *
     * @param sign 标识信息
     */
    public void deleteSign(String sign) {
        if (StringUtils.isNotBlank(sign)) {
            // 删除私钥和公钥信息
            store.value().remove(ConstantCommon.RSA_PRIVATE_KEY + sign);
            store.value().remove(ConstantCommon.RSA_PUBLIC_KEY + sign);
        }
    }

}
